package com.obixlabs.security.credentialsstore.server.dao.ldapimpl;

import static com.obixlabs.security.credentialsstore.server.dao.ldapimpl.LDAPConstants.COMMON_NAME_ATTRIBUTE;
import static com.obixlabs.security.credentialsstore.server.dao.ldapimpl.LDAPConstants.EMAIL_ADDRESS_ATTR_NAME;
import static com.obixlabs.security.credentialsstore.server.dao.ldapimpl.LDAPConstants.OBJECT_CLASS_ATTRIBUTE;
import static com.obixlabs.security.credentialsstore.server.dao.ldapimpl.LDAPConstants.PASSWORD_ATTR_NAME;
import static com.obixlabs.security.credentialsstore.server.dao.ldapimpl.LDAPConstants.USERID_ATTR_NAME;
import static com.obixlabs.security.credentialsstore.server.dao.ldapimpl.LDAPConstants.USER_GIVEN_NAME_ATTR_NAME;
import static com.obixlabs.security.credentialsstore.server.dao.ldapimpl.LDAPConstants.USER_OBJ_CLASS_ATTR_VALS;
import static com.obixlabs.security.credentialsstore.server.dao.ldapimpl.LDAPConstants.USER_SURNAME_ATTR_NAME;

import java.util.List;

import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;

import com.obixlabs.security.credentialsstore.model.BaseUser;
import com.obixlabs.security.credentialsstore.model.ObixGroup;
import com.obixlabs.security.credentialsstore.model.ObixPermission;
import com.obixlabs.security.credentialsstore.model.User;
import com.obixlabs.security.credentialsstore.server.dao.ldapimpl.config.BaseCategorizationConfig;
import com.obixlabs.security.credentialsstore.server.dao.ldapimpl.config.GroupCategorizationConfig;
import com.obixlabs.security.credentialsstore.server.dao.ldapimpl.config.PermissionCategorizationConfig;
import com.obixlabs.security.credentialsstore.server.dao.ldapimpl.config.UserCategorizationConfig;

class LDAPAttributesFactory
{
	private static String ATTR_SEPERATOR_CHAR = ",";
	
	static final String NAME_SEPERATOR_CHAR = " ";
	
	static String getPermissionDN(ObixPermission permission,
									PermissionCategorizationConfig categorizationInfo)
	{
		return new 	StringBuffer()
					.append(COMMON_NAME_ATTRIBUTE)
					.append("=")
					.append(permission.getName())
					.append(",")
					.append(categorizationInfo.getPermissionsBaseDN())
					.toString();
	}	
	
    static void addOrgIdentificationAttributes(	Attributes container, 
    											BaseCategorizationConfig categorizationConfig)
    {
    	addAttributeValuesToContainer(	container, LDAPConstants.ORGANIZATION_UNIT_ATTR_NAME, 
    									categorizationConfig.getOrgUnits());
    	addAttributeValuesToContainer(	container, LDAPConstants.ORGANIZATION_ATTR_NAME, 
				categorizationConfig.getOrganizations());    	
    }
    
    
    static String getGroupDN(	ObixGroup group,
								GroupCategorizationConfig categorizationInfo)
	{
		return new StringBuffer().append(COMMON_NAME_ATTRIBUTE + "=")
									.append(group.getName())
									.append(ATTR_SEPERATOR_CHAR)
									.append(categorizationInfo.getGroupsBaseDN())
									.toString();
	}	
	
	
	static String getUserDN(BaseUser user, 
							UserCategorizationConfig categorizationInfo) 
	{
		return getUserDN(user.getUserId(), categorizationInfo);
	}

	static String getUserDN(String userId,
							UserCategorizationConfig categorizationInfo)
	{
		return new StringBuffer().append(USERID_ATTR_NAME + "=").append(
								userId).append(ATTR_SEPERATOR_CHAR).append(
										categorizationInfo.getUsersBaseDN()).toString();
	}
	
	
	static Attributes createUserAttributes(	BaseUser user,
											boolean fillOutMissingMandatoryFields)
	{
        Attributes result = new BasicAttributes();

        // Create the objectclass to add
        Attribute objClasses = new BasicAttribute(OBJECT_CLASS_ATTRIBUTE);
        for (String attrValue : USER_OBJ_CLASS_ATTR_VALS)
        	objClasses.add(attrValue);

        result.put(objClasses);
        
        //set userId
        Attribute uid = new BasicAttribute(USERID_ATTR_NAME, 
        									user.getUserId());
        result.put(uid);

        //set password
        Attribute userPassword =
            new BasicAttribute(PASSWORD_ATTR_NAME, user.getPassword());
        result.put(userPassword);
        
        if (user.getEmailAddress()!=null)
        {
        	Attribute emailAddressAttr = new BasicAttribute(
        				EMAIL_ADDRESS_ATTR_NAME,user.getEmailAddress());
        	result.put(emailAddressAttr);
        }
        
        if (fillOutMissingMandatoryFields)
        {
            Attribute sn = new BasicAttribute(	USER_SURNAME_ATTR_NAME, " ");
            result.put(sn);  

            Attribute cn = new BasicAttribute(	COMMON_NAME_ATTRIBUTE, 
												user.getUserId());
            result.put(cn);            
        }
        
        return result;        	
	}
	
	static Attributes createHumanUserAttributes(User user)
	{
		Attributes result = createUserAttributes(user, false);
		
        //create matching common name (cn) attribute		
        String cnValue = createCommonName(user.getFirstName(), user.getLastName());         
        Attribute cn = new BasicAttribute(	COMMON_NAME_ATTRIBUTE, 
        									cnValue);
        result.put(cn);
        
        //create givenName (first name) attribute
        Attribute givenName = new BasicAttribute(USER_GIVEN_NAME_ATTR_NAME, 
        										user.getFirstName());
        result.put(givenName);
        
        //create surname attribute
        Attribute sn = new BasicAttribute(	USER_SURNAME_ATTR_NAME, 
        									user.getLastName());
        result.put(sn);

        return result;        
	}
	
    //create the common name by concatenating first and
	//last name with a space in between	
	static String createCommonName(String firstName, String lastName)
	{
        StringBuffer result = 
        			new StringBuffer(firstName)
        			.append(NAME_SEPERATOR_CHAR) //space to seperate first name and surname
        			.append(lastName);
		return result.toString();
	}
		
	static void extractAttributeValsIntoBaseUser(
											Attributes attributes,
											BaseUser user)
											throws NamingException
	{
		String userId = extractAttributeValue(attributes, USERID_ATTR_NAME);
		user.setUserId(userId);
		
		String password = extractAttributeValue(attributes, PASSWORD_ATTR_NAME);
		user.setPassword(password);
		
		String emailAddress = extractAttributeValue(attributes, 
												EMAIL_ADDRESS_ATTR_NAME);
		user.setEmailAddress(emailAddress);
		
	}
	
	static User extractUserDetailsFromAttributes(
											Attributes attributes)
											throws NamingException
	{
		User result = new User();
		
		extractAttributeValsIntoBaseUser(attributes,result);
		
		String givenName = extractAttributeValue(attributes, 
									USER_GIVEN_NAME_ATTR_NAME);
		result.setFirstName(givenName);
		
		
		String surname = extractAttributeValue(attributes, USER_SURNAME_ATTR_NAME);
		result.setLastName(surname);
		
		return result;
	}
	
	static String extractAttributeValue(Attributes attributes,
										String attributeName)
										throws NamingException
	{
		String result;
		
		Attribute attribute = attributes.get(attributeName);
		if (attribute!=null && attribute.get()!=null)
			result = attribute.get().toString();
		else result = null;
		return result;
	}
	
    static void addAttributeValuesToContainer(	Attributes container,
    											String attributeName, 
    											List<String> attributeValues)
    {
    	if (attributeValues.size()>0)
    	{
    		Attribute attribute = new BasicAttribute(attributeName,attributeValues.get(0));    		
    		for (int i =1; i< attributeValues.size();i++)
    				attribute.add(attributeValues.get(i));
    		
    		container.put(attribute);
    	}
    }
		
}//end class def